
MovingPandas offers functions to compute and/or visualize the speed of movement along the trajectory between consecutive points.
import pandas as pd
import geopandas as gpd
import movingpandas as mpd
import shapely as shp
import hvplot.pandas
from geopandas import GeoDataFrame, read_file
from shapely.geometry import Point, LineString, Polygon
from datetime import datetime, timedelta
from holoviews import opts
import warnings
warnings.filterwarnings('ignore')
opts.defaults(opts.Overlay(active_tools=['wheel_zoom'], frame_width=500, frame_height=400))
mpd.show_versions()
MovingPandas 0.11.rc1 SYSTEM INFO ----------- python : 3.9.13 | packaged by conda-forge | (main, May 27 2022, 16:50:36) [MSC v.1929 64 bit (AMD64)] executable : H:\miniconda3\envs\movingpandas\python.exe machine : Windows-10-10.0.19043-SP0 GEOS, GDAL, PROJ INFO --------------------- GEOS : None GEOS lib : None GDAL : 3.5.0 GDAL data dir: None PROJ : 9.0.0 PROJ data dir: H:\miniconda3\pkgs\proj-9.0.0-h1cfcee9_1\Library\share\proj PYTHON DEPENDENCIES ------------------- geopandas : 0.11.1 pandas : 1.4.3 fiona : 1.8.21 numpy : 1.23.1 shapely : 1.8.2 rtree : 1.0.0 pyproj : 3.3.0 matplotlib : 3.5.2 mapclassify: 2.4.3 geopy : 2.2.0 holoviews : 1.14.8 hvplot : 0.8.0 geoviews : 1.9.5 stonesoup : 0.1b9
df = pd.DataFrame([
{'geometry':Point(0,0), 't':datetime(2018,1,1,12,0,0)},
{'geometry':Point(6,0), 't':datetime(2018,1,1,12,0,6)},
{'geometry':Point(6,6), 't':datetime(2018,1,1,12,0,11)},
{'geometry':Point(9,9), 't':datetime(2018,1,1,12,0,14)}
]).set_index('t')
gdf = GeoDataFrame(df, crs=31256)
toy_traj = mpd.Trajectory(gdf, 1)
toy_traj
Trajectory 1 (2018-01-01 12:00:00 to 2018-01-01 12:00:14) | Size: 4 | Length: 16.2m Bounds: (0.0, 0.0, 9.0, 9.0) LINESTRING (0 0, 6 0, 6 6, 9 9)
toy_traj.add_speed(overwrite=True)
toy_traj.df
| geometry | speed | |
|---|---|---|
| t | ||
| 2018-01-01 12:00:00 | POINT (0.000 0.000) | 1.000000 |
| 2018-01-01 12:00:06 | POINT (6.000 0.000) | 1.000000 |
| 2018-01-01 12:00:11 | POINT (6.000 6.000) | 1.200000 |
| 2018-01-01 12:00:14 | POINT (9.000 9.000) | 1.414214 |
We can also visualize the speed values:
toy_traj.plot(column="speed", linewidth=5, capstyle='round', legend=True)
<AxesSubplot:>
Similar to speed, we can also add other columns:
toy_traj.add_direction(overwrite=True)
toy_traj.df
| geometry | speed | direction | |
|---|---|---|---|
| t | |||
| 2018-01-01 12:00:00 | POINT (0.000 0.000) | 1.000000 | 90.0 |
| 2018-01-01 12:00:06 | POINT (6.000 0.000) | 1.000000 | 90.0 |
| 2018-01-01 12:00:11 | POINT (6.000 6.000) | 1.200000 | 0.0 |
| 2018-01-01 12:00:14 | POINT (9.000 9.000) | 1.414214 | 45.0 |
toy_traj.add_timedelta(overwrite=True)
toy_traj.df
| geometry | speed | direction | timedelta | |
|---|---|---|---|---|
| t | ||||
| 2018-01-01 12:00:00 | POINT (0.000 0.000) | 1.000000 | 90.0 | NaT |
| 2018-01-01 12:00:06 | POINT (6.000 0.000) | 1.000000 | 90.0 | 0 days 00:00:06 |
| 2018-01-01 12:00:11 | POINT (6.000 6.000) | 1.200000 | 0.0 | 0 days 00:00:05 |
| 2018-01-01 12:00:14 | POINT (9.000 9.000) | 1.414214 | 45.0 | 0 days 00:00:03 |
gdf = read_file('../data/geolife_small.gpkg')
traj_collection = mpd.TrajectoryCollection(gdf, 'trajectory_id', t='t')
my_traj = traj_collection.trajectories[1]
my_traj.df
| id | sequence | trajectory_id | tracker | geometry | |
|---|---|---|---|---|---|
| t | |||||
| 2009-06-29 07:02:25 | 1556 | 1090 | 2 | 0 | POINT (116.59096 40.07196) |
| 2009-06-29 07:02:30 | 1557 | 1091 | 2 | 0 | POINT (116.59091 40.07201) |
| 2009-06-29 07:02:35 | 1558 | 1092 | 2 | 0 | POINT (116.59088 40.07203) |
| 2009-06-29 07:02:40 | 1559 | 1093 | 2 | 0 | POINT (116.59091 40.07200) |
| 2009-06-29 07:02:45 | 1560 | 1094 | 2 | 0 | POINT (116.59096 40.07198) |
| ... | ... | ... | ... | ... | ... |
| 2009-06-29 11:09:47 | 2448 | 1982 | 2 | 0 | POINT (116.32349 40.00037) |
| 2009-06-29 11:09:57 | 2449 | 1983 | 2 | 0 | POINT (116.32513 40.00057) |
| 2009-06-29 11:10:02 | 2450 | 1984 | 2 | 0 | POINT (116.32688 40.00087) |
| 2009-06-29 11:10:07 | 2451 | 1985 | 2 | 0 | POINT (116.32722 40.00101) |
| 2009-06-29 11:13:12 | 2452 | 1986 | 2 | 0 | POINT (116.32746 40.00052) |
897 rows × 5 columns
Even if the GeoDataFrame does not contain a speed column, we can still plot movement speed:
my_traj.plot(column='speed', linewidth=5, capstyle='round', figsize=(9,3), legend=True, vmax=20)
<AxesSubplot:>
my_traj.hvplot(c='speed', clim=(0,20), line_width=7.0, tiles='CartoLight', cmap='Viridis', colorbar=True)
traj_collection.plot(column='speed', linewidth=5, capstyle='round', legend=True, vmax=20)